package com.songlanyun.modules.freighttemplate.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.songlanyun.common.enums.OrderConstant;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.validator.ValidatorUtils;
import com.songlanyun.common.validator.group.AddGroup;
import com.songlanyun.common.validator.group.UpdateGroup;
import com.songlanyun.modules.exception.GoodsExceptionEnum;

import com.songlanyun.modules.freighttemplate.entity.FreightTemplateRule;
import com.songlanyun.modules.freighttemplate.model.dto.FreightTemplateDTO;
import com.songlanyun.modules.freighttemplate.model.vo.FreightSlim;
import com.songlanyun.modules.freighttemplate.service.FreightTemplateRuleService;
import com.songlanyun.modules.goods.entity.Goods;
import com.songlanyun.modules.goods.service.GoodsService;
import com.songlanyun.modules.shop.entity.ShopEntity;
import com.songlanyun.modules.shop.service.ShopService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songlanyun.common.utils.PageUtils;
import com.songlanyun.common.utils.Query;

import com.songlanyun.modules.freighttemplate.dao.FreightTemplateDao;
import com.songlanyun.modules.freighttemplate.entity.FreightTemplate;
import com.songlanyun.modules.freighttemplate.service.FreightTemplateService;
import org.springframework.transaction.annotation.Transactional;


@Service("freightTemplateService")
public class FreightTemplateServiceImpl extends ServiceImpl<FreightTemplateDao, FreightTemplate> implements FreightTemplateService {


    @Autowired
    private ShopService shopService;
    @Autowired
    private FreightTemplateRuleService freightTemplateRuleService;

    @Autowired
    private GoodsService goodsService;


    @Override
    public FreightTemplate create(FreightTemplate entity) {
        ValidatorUtils.validateEntity(entity, AddGroup.class);
        this.baseMapper.insert(entity);
        return entity;
    }

    private void defaultSet(FreightTemplate entity) {
        FreightTemplate defaultBy = this.baseMapper.getFTemplateDefaultBy(entity.getShopId());
        if (entity.getGeneral()) {
            if (defaultBy != null && !defaultBy.equals(entity)) {
                defaultBy.setGeneral(false);
                modify(defaultBy);
            }
        } else {
            if (defaultBy == null) {
                /**
                 * 这里是必须保证有一条默认的运费模板
                 */
                entity.setGeneral(true);
            }
        }
    }

    @Override
    public FreightTemplate modify(FreightTemplate entity) {
        ValidatorUtils.validateEntity(entity, UpdateGroup.class);
        this.baseMapper.updateById(entity);
        return entity;
    }

    @Override
    public void remove(Integer id) {
        this.removeById(id);
    }

    @Override
    @Transactional
    public void delete(Long shopId, Integer id) {
        ShopEntity shopEntity = shopService.loadShopBy(shopId, true);
        FreightTemplate fTemplateBy = this.validateExist(shopEntity.getId(), id);
        if (fTemplateBy.getGeneral()) {
            throw new RRException(GoodsExceptionEnum.DEFAULT_FREIGHT_TEMPLATE_NEED);
        }
        int i = goodsService.countByTemplate(id);
        if(i>0)
        {
            throw new RRException(GoodsExceptionEnum.FREIGHT_TEMPLATE_RELEVANCE_GOODS);
        }
        freightTemplateRuleService.remove(new LambdaQueryWrapper<FreightTemplateRule>()
                .eq(FreightTemplateRule::getFreightTemplateId, fTemplateBy.getId()));
        this.remove(id);

    }


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<FreightTemplate> page = this.page(
                new Query<FreightTemplate>().getPage(params),
                new QueryWrapper<FreightTemplate>()
        );

        return new PageUtils(page);
    }

    /**
     * 创建运费模板
     *
     * @param shopId
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public FreightTemplate add(Long shopId, FreightTemplateDTO dto) {
        ShopEntity shopEntity = shopService.loadShopBy(shopId, true);
        Integer count = this.baseMapper.selectCount(
                new LambdaQueryWrapper<FreightTemplate>()
                        .eq(FreightTemplate::getShopId, shopEntity.getId())
        );
        if (count >= 10) {
            throw new RRException(GoodsExceptionEnum.FREIGHT_TEMPLATE_COUNT);
        }


        /**
         * 创建运费模板
         */
        FreightTemplate obj = new FreightTemplate();
        BeanUtils.copyProperties(dto, obj);
        obj.setFreightComputeMode(OrderConstant.FreightComputeMode.getByCode(dto.getFreightComputeMode()));
        obj.setShopId(shopId);
        defaultSet(obj);
        this.create(obj);

        /**
         * 创建默认模板规则
         */
        dto.getDefaultRule().setFreightComputeMode(dto.getFreightComputeMode());
        dto.getDefaultRule().setGeneral(true);
        freightTemplateRuleService.add(obj.getId(), dto.getDefaultRule());
        return obj;
    }

    /**
     * 修改运费模板
     *
     * @param shopId
     * @param dto
     * @return
     */
    @Transactional
    @Override
    public FreightTemplate update(Long shopId, FreightTemplateDTO dto) {
        ShopEntity shopEntity = shopService.loadShopBy(shopId, true);
        FreightTemplate template = this.validateExist(shopEntity.getId(), dto.getId());
        BeanUtils.copyProperties(dto, template);
        template.setShopId(shopId);
        template.setFreightComputeMode(OrderConstant.FreightComputeMode.getByCode(dto.getFreightComputeMode()));

        defaultSet(template);
        this.modify(template);

        dto.getDefaultRule().setFreightComputeMode(dto.getFreightComputeMode());
        FreightTemplateRule df = freightTemplateRuleService.update(template.getId(), template.getDefaultRule().getId(), dto.getDefaultRule());

        template.setDefaultRule(df);
        return template;
    }


    private FreightTemplate validateExist(Long shopId, Integer id) {
        FreightTemplate template = this.baseMapper.getFTemplateBy(shopId, id);
        if (template == null) {
            throw new RRException(GoodsExceptionEnum.FREIGHT_TEMPLATE_NOT_EXISTS);
        }
        return template;
    }

    @Override
    public FreightTemplate getFTemplateBy(Long shopId, Integer id) {
        return this.baseMapper.getFTemplateBy(shopId, id);
    }

    /**
     * 设置当前运费模板为默认模板
     *
     * @param shopId
     * @param id
     */
    @Transactional
    @Override
    public void setDefault(Long shopId, Integer id) {
        ShopEntity shopEntity = shopService.loadShopBy(shopId, true);
        FreightTemplate template = validateExist(shopEntity.getId(), id);
        template.setGeneral(true);

        FreightTemplate defaultFt = this.baseMapper.getFTemplateDefaultBy(shopId);
        if (defaultFt != null) {
            //如果之前有运费模板要改之前的改成非默认
            defaultFt.setGeneral(false);
            this.updateById(defaultFt);
        }

        this.updateById(template);
    }




    @Override
    public List<FreightTemplate> all(Long shopId) {
        LambdaQueryWrapper<FreightTemplate> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FreightTemplate::getShopId, shopId);
        List<FreightTemplate> list = this.list(wrapper);
        list = list.stream().sorted((o1, o2) -> {
            if (o1.getGeneral()) {
                return 1;
            } else {
                return 0;
            }
        }).collect(Collectors.toList());
        return list;
    }

    @Override
    public List<FreightSlim> slimList(Long shopId) {
        List<FreightSlim> list = this.baseMapper.getSlimList(shopId);
        return list;
    }

    @Override
    public FreightTemplate getFTemplateDefaultBy(Long shopId) {
        return this.baseMapper.getFTemplateDefaultBy(shopId);
    }

    @Override
    public FreightTemplate getFreeTemplate(Long shopId) {
        FreightTemplate template = this.baseMapper.selectOne(new LambdaQueryWrapper<FreightTemplate>()
                .eq(FreightTemplate::getShopId, shopId)
                .eq(FreightTemplate::getFreePost, true)
                .last("limit 1"));
        return template;
    }
}
